﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Effects.Effects;
using Effects.Effects.GuiParts;
using Effects.Filters;

// class under construction

namespace EffectsPack
{ 
    
    
    /*
    public class NoiseBox:Effect
    {
        #region controls

        #region footswitch
        // switch for turning the effect ON or OFF

        /// <summary>
        ///  Footswitch for turning the effect On/Off.
        /// </summary>
        private Footswitch footswitch;

        /// <summary>
        ///  Key for the footswitch setting.
        /// </summary>
        /// <remarks>
        ///  Key that identifies footswitch setting. This key will be later used in methods that handle recording changes in parameter settings.
        ///  Remeber that every key must be unique.
        /// </remarks>
        private const int footswitchKey = 0;

        /// <summary>
        ///  Indicates On/Off status of the effect.
        /// </summary>
        private LED led;

        /// <summary>
        ///  Synchornizes led with footswitch.
        /// </summary>
        /// <remarks>
        ///  Useful class that keeps synchornized footswitch and Led for us.
        /// </remarks>
        private FootswitchLedSynchronizer synchronizer;

        #endregion

        #endregion

        #region bassCut

        private double bassCut;

        private double bassCutGain;

        private Pot BassCut;

        private Filter bassCutFilter;

        /// <summary>
        ///  Key for the bass cut parameter
        /// </summary>
        private const int bassCutKey = 1;

        #endregion

        #region highCut

        private double highCut;

        private double highCutGain;

        private Pot HighCut;

        private Filter highCutFilter;

        /// <summary>
        ///  Key for the bass cut parameter
        /// </summary>
        private const int highCutKey = 2;

        #endregion

        #region noise

        private double noiseDepth;
        private double noiseDepth_1;

        private Pot Noise;

        Random noiseGenerator;

        private const int noiseKey = 3;

        #endregion

        #region effects_properties

        /// <summary>
        ///  Gets the name of the effect.
        /// </summary>
        public override string Name
        {
            get
            {
                return "NoiseBox v1.0";
            }
        }

        /// <summary>
        ///  Turns the effect On/Off.
        /// </summary>
        public override bool Switch
        {
            get
            {
                return base.Switch;
            }
            set
            {
                base.Switch = value;

                // synchronizer sets the value to the LED and footswitch
                synchronizer.SetValue(value);
            }
        }

        /// <summary>
        ///  Gets or sets sampling rate of the input signal
        /// </summary>
        public override uint SampleRate
        {
            get{ return base.SampleRate; }
            set
            {
                base.SampleRate = value;
                InitializeFilters();
            }
        }

        #endregion

        #region constructor

        /// <summary>
        ///  Creates new instance.
        /// </summary>
        public NoiseBox()
        {
            //BackgroundImage = System.Drawing.Image.FromStream(new System.IO.MemoryStream(Properties.Resources.Boost));
            InitializeComponents();
            Size = new System.Drawing.Size(300, 200);
            noiseGenerator = new Random();

        }

        /// <summary>
        ///  Initializes pot.
        /// </summary>
        private void InitializeComponents()
        {
            Noise = new Pot();
            Noise.MaxValue = 0.0001;
            Noise.MinValue = 0;
            Noise.ValueChanged += new PotValueChangedEventHandler(this.NoiseDepthMoved);
            Noise.Knob = PotKnob.ChickenKnobMiddle;
            Noise.Location = new System.Drawing.Point(0, 0);
            Controls.Add(Noise);


            BassCut = new Pot();
            BassCut.MaxValue = 12;
            BassCut.MinValue = 0;
            BassCut.ValueChanged += this.BassCutMoved;
            BassCut.Knob = PotKnob.ChickenKnobMiddle;
            BassCut.Location = new System.Drawing.Point(100, 0);
            Controls.Add(BassCut);

            HighCut = new Pot();
            HighCut.MaxValue = 12;
            HighCut.MinValue = 0;
            HighCut.ValueChanged += this.HighCutMoved;
            HighCut.Knob = PotKnob.ChickenKnobMiddle;
            HighCut.Location = new System.Drawing.Point(200, 0);
            Controls.Add(HighCut);



        }

        /// <summary>
        ///  Initializes footswitch and led.
        /// </summary>
        private void InitializeFootswitch()
        {
            // footswitch
            footswitch = new Footswitch();
            switchedOn = true;
            footswitch.On = true;
            footswitch.Switched += new FootswitchSwitchedEventHandler(this.FootswitchSwitched);
            footswitch.Location = new System.Drawing.Point(185, 110);
            Controls.Add(footswitch);

            // led
            led = new LED();
            led.On = true;
            led.Location = new System.Drawing.Point(190, 40);
            Controls.Add(led);

            // synchronization between LED and footswitch
            synchronizer = new FootswitchLedSynchronizer(footswitch, led);
        }


        private void InitializeFilters()
        {
            bassCutFilter = FourthOrderFilter.CreateLowPass(700, (int)sampleRate);
            highCutFilter = FourthOrderFilter.CreateHighPass(1000, (int)sampleRate);
        }

        #endregion

        #region main_work

        /// <summary>
        ///  Effects input signal.
        /// </summary>
        /// <param name="data"> Input signal </param>
        /// <returns> Effected output signal </returns>
        public override double[] effect(double[] data)
        {
            double[] retData = new double[data.Length];

            double inp;

            for (int i = 0; i < data.Length; i++)
            {
                inp = noiseDepth * (2 * noiseGenerator.NextDouble() - 1) + noiseDepth_1 * data[i];

                retData[i] = inp + bassCutGain * bassCutFilter.Step(inp) + highCutGain * highCutFilter.Step(inp);
            }

            return retData;
        }

        #endregion

        #region controls_event_handlers


        /// <summary>
        ///  Footswitch.Switched event handler. Turns effect On or Off accordingly to the event arguments.
        /// </summary>
        /// <param name="sender"> Object that has raised the event </param>
        /// <param name="args"> Event arguments </param>
        protected void FootswitchSwitched(object sender, FootswitchSwitchedEventArgs args)
        {
            this.switchedOn = args.On;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(footswitchKey, switchedOn);
            if (SettingsChanged != null)
                this.SettingsChanged(this, changeArgs);
        }

        private void BassCutMoved(object sender, PotValueChangedEventArgs e)
        {
            bassCut = e.NewValue;
            bassCutGain = Math.Pow(10, bassCut * -0.05) - 1;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(bassCutKey, bassCut);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        private void HighCutMoved(object sender, PotValueChangedEventArgs e)
        {
            highCut = e.NewValue;
            highCutGain = Math.Pow(10, highCut * -0.05) - 1;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(bassCutKey, highCut);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }



        private void NoiseDepthMoved(object sender, PotValueChangedEventArgs e)
        {
            noiseDepth = e.NewValue;
            noiseDepth_1 = 1 - noiseDepth;

            EffectSettingsChangedEventArgs changeArgs = new EffectSettingsChangedEventArgs(noiseKey, noiseDepth);
            if (SettingsChanged != null)
                SettingsChanged(this, changeArgs);
        }

        #endregion

        #region settings
        // Getting and setting the settings of volume effect

        /// <summary>
        ///  Raised when any parameter of effect is changed.
        /// </summary>
        /// <remarks> 
        ///  We raise this event whenewer user changes any control (Volume pot or footswitch).
        /// </remarks>
        public override event EffectSettingsChangedDelegate SettingsChanged;

        /// <summary>
        ///  Sets settings 
        /// </summary>
        /// <param name="e"> Settings that are to be changed </param>
        /// <remarks>
        public override void SetSetting(EffectSettingsChangedEventArgs e)
        {
            // all keys in this class are integers
            int key = (int)e.Key;


            // is it footswitch settings?
            if (key == footswitchKey)
            {
                switchedOn = (bool)e.Value;
                synchronizer.SetValue(switchedOn);
                return;
            }
        }

        /// <summary>
        ///  Gets all current settings.
        /// </summary>
        /// <returns> All current settings </returns>
        /// <remarks>
        ///  We return array that contains all current settings of the effect. In our case it means, volume level and footswitch state.
        ///  Note the order of parameters in the array is the same as is returned by GetParameters method.
        /// </remarks>
        public override object[] GetAllSettings()
        {
            object[] settings = new object[2];
            settings[0] = switchedOn;

            return settings;
        }

        /// <summary>
        ///  Sets all settings.
        /// </summary>
        /// <param name="settings"> Settings to set. This argument should be taken from GetAllSettings previously </param>
        /// <remarks>
        ///  We set all parameters. Passed array has the same structure as the one returned by GetAllSettings method.
        /// </remarks>
        public override void SetAllSettings(object[] settings)
        {
            object[] sets = (object[])settings;

            switchedOn = (bool)sets[0];
            synchronizer.SetValue(switchedOn);

        }


        /// <summary>
        ///  Gets array containing all effect's parameters.
        /// </summary>
        /// <returns> Array containing description fo all parameters </returns>
        /// <remarks>
        ///  In here we describe all parameters of the effect. Remember that order of them in returned array is important and same order
        ///  must be used in GetAllSettings and GetAllSettings methods.
        /// </remarks>
        public override EffectParam[] GetParameters()
        {
            // we have two parameters
            EffectParam[] parameters = new EffectParam[2];

            /* footswitch settings: we describe it as list type, with two values
             *    To which we set string and value */ /*
            ListItem[] footswitchState = new ListItem[2];
            footswitchState[0] = new ListItem("Turn on", true);
            footswitchState[1] = new ListItem("Turn off", false);

            /*  parameters ar described by key, string displayed to the user and bounds (or list enumeration)
             * Note that for volume parameter we must pass float value to use appropriate constructor */ /*
            parameters[0] = new EffectParam(footswitchKey, "ON/OFF", footswitchState);
           
            return parameters;
        }

        #endregion

    }
  */                                                                                                          
}
